home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / compiler / pycodegen.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2005-10-18  |  50KB  |  1,656 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. import imp
  5. import os
  6. import marshal
  7. import struct
  8. import sys
  9. import types
  10. from cStringIO import StringIO
  11. from compiler import ast, parse, walk, syntax
  12. from compiler import pyassem, misc, future, symbols
  13. from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
  14. from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS, CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION
  15. from compiler.pyassem import TupleArg
  16.  
  17. try:
  18.     VERSION = sys.version_info[0]
  19. except AttributeError:
  20.     VERSION = 1
  21.  
  22. callfunc_opcode_info = {
  23.     (0, 0): 'CALL_FUNCTION',
  24.     (1, 0): 'CALL_FUNCTION_VAR',
  25.     (0, 1): 'CALL_FUNCTION_KW',
  26.     (1, 1): 'CALL_FUNCTION_VAR_KW' }
  27. LOOP = 1
  28. EXCEPT = 2
  29. TRY_FINALLY = 3
  30. END_FINALLY = 4
  31.  
  32. def compileFile(filename, display = 0):
  33.     f = open(filename, 'U')
  34.     buf = f.read()
  35.     f.close()
  36.     mod = Module(buf, filename)
  37.     
  38.     try:
  39.         mod.compile(display)
  40.     except SyntaxError:
  41.         raise 
  42.  
  43.     f = open(filename + 'c', 'wb')
  44.     mod.dump(f)
  45.     f.close()
  46.  
  47.  
  48. def compile(source, filename, mode, flags = None, dont_inherit = None):
  49.     '''Replacement for builtin compile() function'''
  50.     if flags is not None or dont_inherit is not None:
  51.         raise RuntimeError, 'not implemented yet'
  52.     
  53.     if mode == 'single':
  54.         gen = Interactive(source, filename)
  55.     elif mode == 'exec':
  56.         gen = Module(source, filename)
  57.     elif mode == 'eval':
  58.         gen = Expression(source, filename)
  59.     else:
  60.         raise ValueError("compile() 3rd arg must be 'exec' or 'eval' or 'single'")
  61.     gen.compile()
  62.     return gen.code
  63.  
  64.  
  65. class AbstractCompileMode:
  66.     mode = None
  67.     
  68.     def __init__(self, source, filename):
  69.         self.source = source
  70.         self.filename = filename
  71.         self.code = None
  72.  
  73.     
  74.     def _get_tree(self):
  75.         tree = parse(self.source, self.mode)
  76.         misc.set_filename(self.filename, tree)
  77.         syntax.check(tree)
  78.         return tree
  79.  
  80.     
  81.     def compile(self):
  82.         pass
  83.  
  84.     
  85.     def getCode(self):
  86.         return self.code
  87.  
  88.  
  89.  
  90. class Expression(AbstractCompileMode):
  91.     mode = 'eval'
  92.     
  93.     def compile(self):
  94.         tree = self._get_tree()
  95.         gen = ExpressionCodeGenerator(tree)
  96.         self.code = gen.getCode()
  97.  
  98.  
  99.  
  100. class Interactive(AbstractCompileMode):
  101.     mode = 'single'
  102.     
  103.     def compile(self):
  104.         tree = self._get_tree()
  105.         gen = InteractiveCodeGenerator(tree)
  106.         self.code = gen.getCode()
  107.  
  108.  
  109.  
  110. class Module(AbstractCompileMode):
  111.     mode = 'exec'
  112.     
  113.     def compile(self, display = 0):
  114.         tree = self._get_tree()
  115.         gen = ModuleCodeGenerator(tree)
  116.         if display:
  117.             import pprint as pprint
  118.             print pprint.pprint(tree)
  119.         
  120.         self.code = gen.getCode()
  121.  
  122.     
  123.     def dump(self, f):
  124.         f.write(self.getPycHeader())
  125.         marshal.dump(self.code, f)
  126.  
  127.     MAGIC = imp.get_magic()
  128.     
  129.     def getPycHeader(self):
  130.         mtime = os.path.getmtime(self.filename)
  131.         mtime = struct.pack('<i', mtime)
  132.         return self.MAGIC + mtime
  133.  
  134.  
  135.  
  136. class LocalNameFinder:
  137.     '''Find local names in scope'''
  138.     
  139.     def __init__(self, names = ()):
  140.         self.names = misc.Set()
  141.         self.globals = misc.Set()
  142.         for name in names:
  143.             self.names.add(name)
  144.         
  145.  
  146.     
  147.     def getLocals(self):
  148.         for elt in self.globals.elements():
  149.             if self.names.has_elt(elt):
  150.                 self.names.remove(elt)
  151.                 continue
  152.         
  153.         return self.names
  154.  
  155.     
  156.     def visitDict(self, node):
  157.         pass
  158.  
  159.     
  160.     def visitGlobal(self, node):
  161.         for name in node.names:
  162.             self.globals.add(name)
  163.         
  164.  
  165.     
  166.     def visitFunction(self, node):
  167.         self.names.add(node.name)
  168.  
  169.     
  170.     def visitLambda(self, node):
  171.         pass
  172.  
  173.     
  174.     def visitImport(self, node):
  175.         for name, alias in node.names:
  176.             if not alias:
  177.                 pass
  178.             self.names.add(name)
  179.         
  180.  
  181.     
  182.     def visitFrom(self, node):
  183.         for name, alias in node.names:
  184.             if not alias:
  185.                 pass
  186.             self.names.add(name)
  187.         
  188.  
  189.     
  190.     def visitClass(self, node):
  191.         self.names.add(node.name)
  192.  
  193.     
  194.     def visitAssName(self, node):
  195.         self.names.add(node.name)
  196.  
  197.  
  198.  
  199. def is_constant_false(node):
  200.     if isinstance(node, ast.Const):
  201.         if not node.value:
  202.             return 1
  203.         
  204.     
  205.     return 0
  206.  
  207.  
  208. class CodeGenerator:
  209.     '''Defines basic code generator for Python bytecode
  210.  
  211.     This class is an abstract base class.  Concrete subclasses must
  212.     define an __init__() that defines self.graph and then calls the
  213.     __init__() defined in this class.
  214.  
  215.     The concrete class must also define the class attributes
  216.     NameFinder, FunctionGen, and ClassGen.  These attributes can be
  217.     defined in the initClass() method, which is a hook for
  218.     initializing these methods after all the classes have been
  219.     defined.
  220.     '''
  221.     optimized = 0
  222.     __initialized = None
  223.     class_name = None
  224.     
  225.     def __init__(self):
  226.         if self._CodeGenerator__initialized is None:
  227.             self.initClass()
  228.             self.__class__._CodeGenerator__initialized = 1
  229.         
  230.         self.checkClass()
  231.         self.locals = misc.Stack()
  232.         self.setups = misc.Stack()
  233.         self.last_lineno = None
  234.         self._setupGraphDelegation()
  235.         self._div_op = 'BINARY_DIVIDE'
  236.         futures = self.get_module().futures
  237.         for feature in futures:
  238.             if feature == 'division':
  239.                 self.graph.setFlag(CO_FUTURE_DIVISION)
  240.                 self._div_op = 'BINARY_TRUE_DIVIDE'
  241.                 continue
  242.             if feature == 'generators':
  243.                 self.graph.setFlag(CO_GENERATOR_ALLOWED)
  244.                 continue
  245.         
  246.  
  247.     
  248.     def initClass(self):
  249.         '''This method is called once for each class'''
  250.         pass
  251.  
  252.     
  253.     def checkClass(self):
  254.         '''Verify that class is constructed correctly'''
  255.         
  256.         try:
  257.             if not hasattr(self, 'graph'):
  258.                 raise AssertionError
  259.             if not getattr(self, 'NameFinder'):
  260.                 raise AssertionError
  261.             if not getattr(self, 'FunctionGen'):
  262.                 raise AssertionError
  263.             if not getattr(self, 'ClassGen'):
  264.                 raise AssertionError
  265.         except AssertionError:
  266.             msg = None
  267.             intro = 'Bad class construction for %s' % self.__class__.__name__
  268.             raise AssertionError, intro
  269.  
  270.  
  271.     
  272.     def _setupGraphDelegation(self):
  273.         self.emit = self.graph.emit
  274.         self.newBlock = self.graph.newBlock
  275.         self.startBlock = self.graph.startBlock
  276.         self.nextBlock = self.graph.nextBlock
  277.         self.setDocstring = self.graph.setDocstring
  278.  
  279.     
  280.     def getCode(self):
  281.         '''Return a code object'''
  282.         return self.graph.getCode()
  283.  
  284.     
  285.     def mangle(self, name):
  286.         if self.class_name is not None:
  287.             return misc.mangle(name, self.class_name)
  288.         else:
  289.             return name
  290.  
  291.     
  292.     def parseSymbols(self, tree):
  293.         s = symbols.SymbolVisitor()
  294.         walk(tree, s)
  295.         return s.scopes
  296.  
  297.     
  298.     def get_module(self):
  299.         raise RuntimeError, 'should be implemented by subclasses'
  300.  
  301.     
  302.     def isLocalName(self, name):
  303.         return self.locals.top().has_elt(name)
  304.  
  305.     
  306.     def storeName(self, name):
  307.         self._nameOp('STORE', name)
  308.  
  309.     
  310.     def loadName(self, name):
  311.         self._nameOp('LOAD', name)
  312.  
  313.     
  314.     def delName(self, name):
  315.         self._nameOp('DELETE', name)
  316.  
  317.     
  318.     def _nameOp(self, prefix, name):
  319.         name = self.mangle(name)
  320.         scope = self.scope.check_name(name)
  321.         if scope == SC_LOCAL:
  322.             if not self.optimized:
  323.                 self.emit(prefix + '_NAME', name)
  324.             else:
  325.                 self.emit(prefix + '_FAST', name)
  326.         elif scope == SC_GLOBAL:
  327.             if not self.optimized:
  328.                 self.emit(prefix + '_NAME', name)
  329.             else:
  330.                 self.emit(prefix + '_GLOBAL', name)
  331.         elif scope == SC_FREE or scope == SC_CELL:
  332.             self.emit(prefix + '_DEREF', name)
  333.         else:
  334.             raise RuntimeError, 'unsupported scope for var %s: %d' % (name, scope)
  335.  
  336.     
  337.     def _implicitNameOp(self, prefix, name):
  338.         """Emit name ops for names generated implicitly by for loops
  339.  
  340.         The interpreter generates names that start with a period or
  341.         dollar sign.  The symbol table ignores these names because
  342.         they aren't present in the program text.
  343.         """
  344.         if self.optimized:
  345.             self.emit(prefix + '_FAST', name)
  346.         else:
  347.             self.emit(prefix + '_NAME', name)
  348.  
  349.     
  350.     def set_lineno(self, node, force = False):
  351.         '''Emit SET_LINENO if necessary.
  352.  
  353.         The instruction is considered necessary if the node has a
  354.         lineno attribute and it is different than the last lineno
  355.         emitted.
  356.  
  357.         Returns true if SET_LINENO was emitted.
  358.  
  359.         There are no rules for when an AST node should have a lineno
  360.         attribute.  The transformer and AST code need to be reviewed
  361.         and a consistent policy implemented and documented.  Until
  362.         then, this method works around missing line numbers.
  363.         '''
  364.         lineno = getattr(node, 'lineno', None)
  365.         if lineno is not None:
  366.             if lineno != self.last_lineno or force:
  367.                 self.emit('SET_LINENO', lineno)
  368.                 self.last_lineno = lineno
  369.                 return True
  370.             
  371.         return False
  372.  
  373.     NameFinder = LocalNameFinder
  374.     FunctionGen = None
  375.     ClassGen = None
  376.     
  377.     def visitModule(self, node):
  378.         self.scopes = self.parseSymbols(node)
  379.         self.scope = self.scopes[node]
  380.         self.emit('SET_LINENO', 0)
  381.         if node.doc:
  382.             self.emit('LOAD_CONST', node.doc)
  383.             self.storeName('__doc__')
  384.         
  385.         lnf = walk(node.node, self.NameFinder(), verbose = 0)
  386.         self.locals.push(lnf.getLocals())
  387.         self.visit(node.node)
  388.         self.emit('LOAD_CONST', None)
  389.         self.emit('RETURN_VALUE')
  390.  
  391.     
  392.     def visitExpression(self, node):
  393.         self.set_lineno(node)
  394.         self.scopes = self.parseSymbols(node)
  395.         self.scope = self.scopes[node]
  396.         self.visit(node.node)
  397.         self.emit('RETURN_VALUE')
  398.  
  399.     
  400.     def visitFunction(self, node):
  401.         self._visitFuncOrLambda(node, isLambda = 0)
  402.         if node.doc:
  403.             self.setDocstring(node.doc)
  404.         
  405.         self.storeName(node.name)
  406.  
  407.     
  408.     def visitLambda(self, node):
  409.         self._visitFuncOrLambda(node, isLambda = 1)
  410.  
  411.     
  412.     def _visitFuncOrLambda(self, node, isLambda = 0):
  413.         if not isLambda and node.decorators:
  414.             for decorator in node.decorators.nodes:
  415.                 self.visit(decorator)
  416.             
  417.             ndecorators = len(node.decorators.nodes)
  418.         else:
  419.             ndecorators = 0
  420.         gen = self.FunctionGen(node, self.scopes, isLambda, self.class_name, self.get_module())
  421.         walk(node.code, gen)
  422.         gen.finish()
  423.         self.set_lineno(node)
  424.         for default in node.defaults:
  425.             self.visit(default)
  426.         
  427.         frees = gen.scope.get_free_vars()
  428.         if frees:
  429.             for name in frees:
  430.                 self.emit('LOAD_CLOSURE', name)
  431.             
  432.             self.emit('LOAD_CONST', gen)
  433.             self.emit('MAKE_CLOSURE', len(node.defaults))
  434.         else:
  435.             self.emit('LOAD_CONST', gen)
  436.             self.emit('MAKE_FUNCTION', len(node.defaults))
  437.         for i in range(ndecorators):
  438.             self.emit('CALL_FUNCTION', 1)
  439.         
  440.  
  441.     
  442.     def visitClass(self, node):
  443.         gen = self.ClassGen(node, self.scopes, self.get_module())
  444.         walk(node.code, gen)
  445.         gen.finish()
  446.         self.set_lineno(node)
  447.         self.emit('LOAD_CONST', node.name)
  448.         for base in node.bases:
  449.             self.visit(base)
  450.         
  451.         self.emit('BUILD_TUPLE', len(node.bases))
  452.         frees = gen.scope.get_free_vars()
  453.         for name in frees:
  454.             self.emit('LOAD_CLOSURE', name)
  455.         
  456.         self.emit('LOAD_CONST', gen)
  457.         if frees:
  458.             self.emit('MAKE_CLOSURE', 0)
  459.         else:
  460.             self.emit('MAKE_FUNCTION', 0)
  461.         self.emit('CALL_FUNCTION', 0)
  462.         self.emit('BUILD_CLASS')
  463.         self.storeName(node.name)
  464.  
  465.     
  466.     def visitIf(self, node):
  467.         end = self.newBlock()
  468.         numtests = len(node.tests)
  469.         for i in range(numtests):
  470.             (test, suite) = node.tests[i]
  471.             if is_constant_false(test):
  472.                 continue
  473.             
  474.             self.set_lineno(test)
  475.             self.visit(test)
  476.             nextTest = self.newBlock()
  477.             self.emit('JUMP_IF_FALSE', nextTest)
  478.             self.nextBlock()
  479.             self.emit('POP_TOP')
  480.             self.visit(suite)
  481.             self.emit('JUMP_FORWARD', end)
  482.             self.startBlock(nextTest)
  483.             self.emit('POP_TOP')
  484.         
  485.         if node.else_:
  486.             self.visit(node.else_)
  487.         
  488.         self.nextBlock(end)
  489.  
  490.     
  491.     def visitWhile(self, node):
  492.         self.set_lineno(node)
  493.         loop = self.newBlock()
  494.         else_ = self.newBlock()
  495.         after = self.newBlock()
  496.         self.emit('SETUP_LOOP', after)
  497.         self.nextBlock(loop)
  498.         self.setups.push((LOOP, loop))
  499.         self.set_lineno(node, force = True)
  500.         self.visit(node.test)
  501.         if not else_:
  502.             pass
  503.         self.emit('JUMP_IF_FALSE', after)
  504.         self.nextBlock()
  505.         self.emit('POP_TOP')
  506.         self.visit(node.body)
  507.         self.emit('JUMP_ABSOLUTE', loop)
  508.         self.startBlock(else_)
  509.         self.emit('POP_TOP')
  510.         self.emit('POP_BLOCK')
  511.         self.setups.pop()
  512.         if node.else_:
  513.             self.visit(node.else_)
  514.         
  515.         self.nextBlock(after)
  516.  
  517.     
  518.     def visitFor(self, node):
  519.         start = self.newBlock()
  520.         anchor = self.newBlock()
  521.         after = self.newBlock()
  522.         self.setups.push((LOOP, start))
  523.         self.set_lineno(node)
  524.         self.emit('SETUP_LOOP', after)
  525.         self.visit(node.list)
  526.         self.emit('GET_ITER')
  527.         self.nextBlock(start)
  528.         self.set_lineno(node, force = 1)
  529.         self.emit('FOR_ITER', anchor)
  530.         self.visit(node.assign)
  531.         self.visit(node.body)
  532.         self.emit('JUMP_ABSOLUTE', start)
  533.         self.nextBlock(anchor)
  534.         self.emit('POP_BLOCK')
  535.         self.setups.pop()
  536.         if node.else_:
  537.             self.visit(node.else_)
  538.         
  539.         self.nextBlock(after)
  540.  
  541.     
  542.     def visitBreak(self, node):
  543.         if not self.setups:
  544.             raise SyntaxError, "'break' outside loop (%s, %d)" % (node.filename, node.lineno)
  545.         
  546.         self.set_lineno(node)
  547.         self.emit('BREAK_LOOP')
  548.  
  549.     
  550.     def visitContinue(self, node):
  551.         if not self.setups:
  552.             raise SyntaxError, "'continue' outside loop (%s, %d)" % (node.filename, node.lineno)
  553.         
  554.         (kind, block) = self.setups.top()
  555.         if kind == LOOP:
  556.             self.set_lineno(node)
  557.             self.emit('JUMP_ABSOLUTE', block)
  558.             self.nextBlock()
  559.         elif kind == EXCEPT or kind == TRY_FINALLY:
  560.             self.set_lineno(node)
  561.             top = len(self.setups)
  562.             while top > 0:
  563.                 top = top - 1
  564.                 (kind, loop_block) = self.setups[top]
  565.                 if kind == LOOP:
  566.                     break
  567.                     continue
  568.             if kind != LOOP:
  569.                 raise SyntaxError, "'continue' outside loop (%s, %d)" % (node.filename, node.lineno)
  570.             
  571.             self.emit('CONTINUE_LOOP', loop_block)
  572.             self.nextBlock()
  573.         elif kind == END_FINALLY:
  574.             msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
  575.             raise SyntaxError, msg % (node.filename, node.lineno)
  576.         
  577.  
  578.     
  579.     def visitTest(self, node, jump):
  580.         end = self.newBlock()
  581.         for child in node.nodes[:-1]:
  582.             self.visit(child)
  583.             self.emit(jump, end)
  584.             self.nextBlock()
  585.             self.emit('POP_TOP')
  586.         
  587.         self.visit(node.nodes[-1])
  588.         self.nextBlock(end)
  589.  
  590.     
  591.     def visitAnd(self, node):
  592.         self.visitTest(node, 'JUMP_IF_FALSE')
  593.  
  594.     
  595.     def visitOr(self, node):
  596.         self.visitTest(node, 'JUMP_IF_TRUE')
  597.  
  598.     
  599.     def visitCompare(self, node):
  600.         self.visit(node.expr)
  601.         cleanup = self.newBlock()
  602.         for op, code in node.ops[:-1]:
  603.             self.visit(code)
  604.             self.emit('DUP_TOP')
  605.             self.emit('ROT_THREE')
  606.             self.emit('COMPARE_OP', op)
  607.             self.emit('JUMP_IF_FALSE', cleanup)
  608.             self.nextBlock()
  609.             self.emit('POP_TOP')
  610.         
  611.         if node.ops:
  612.             (op, code) = node.ops[-1]
  613.             self.visit(code)
  614.             self.emit('COMPARE_OP', op)
  615.         
  616.         if len(node.ops) > 1:
  617.             end = self.newBlock()
  618.             self.emit('JUMP_FORWARD', end)
  619.             self.startBlock(cleanup)
  620.             self.emit('ROT_TWO')
  621.             self.emit('POP_TOP')
  622.             self.nextBlock(end)
  623.         
  624.  
  625.     __list_count = 0
  626.     
  627.     def visitListComp(self, node):
  628.         self.set_lineno(node)
  629.         append = '$append%d' % self._CodeGenerator__list_count
  630.         self._CodeGenerator__list_count = self._CodeGenerator__list_count + 1
  631.         self.emit('BUILD_LIST', 0)
  632.         self.emit('DUP_TOP')
  633.         self.emit('LOAD_ATTR', 'append')
  634.         self._implicitNameOp('STORE', append)
  635.         stack = []
  636.         for i, for_ in zip(range(len(node.quals)), node.quals):
  637.             (start, anchor) = self.visit(for_)
  638.             cont = None
  639.             for if_ in for_.ifs:
  640.                 if cont is None:
  641.                     cont = self.newBlock()
  642.                 
  643.                 self.visit(if_, cont)
  644.             
  645.             stack.insert(0, (start, cont, anchor))
  646.         
  647.         self._implicitNameOp('LOAD', append)
  648.         self.visit(node.expr)
  649.         self.emit('CALL_FUNCTION', 1)
  650.         self.emit('POP_TOP')
  651.         for start, cont, anchor in stack:
  652.             if cont:
  653.                 skip_one = self.newBlock()
  654.                 self.emit('JUMP_FORWARD', skip_one)
  655.                 self.startBlock(cont)
  656.                 self.emit('POP_TOP')
  657.                 self.nextBlock(skip_one)
  658.             
  659.             self.emit('JUMP_ABSOLUTE', start)
  660.             self.startBlock(anchor)
  661.         
  662.         self._implicitNameOp('DELETE', append)
  663.         self._CodeGenerator__list_count = self._CodeGenerator__list_count - 1
  664.  
  665.     
  666.     def visitListCompFor(self, node):
  667.         start = self.newBlock()
  668.         anchor = self.newBlock()
  669.         self.visit(node.list)
  670.         self.emit('GET_ITER')
  671.         self.nextBlock(start)
  672.         self.set_lineno(node, force = True)
  673.         self.emit('FOR_ITER', anchor)
  674.         self.nextBlock()
  675.         self.visit(node.assign)
  676.         return (start, anchor)
  677.  
  678.     
  679.     def visitListCompIf(self, node, branch):
  680.         self.set_lineno(node, force = True)
  681.         self.visit(node.test)
  682.         self.emit('JUMP_IF_FALSE', branch)
  683.         self.newBlock()
  684.         self.emit('POP_TOP')
  685.  
  686.     
  687.     def visitGenExpr(self, node):
  688.         gen = GenExprCodeGenerator(node, self.scopes, self.class_name, self.get_module())
  689.         walk(node.code, gen)
  690.         gen.finish()
  691.         self.set_lineno(node)
  692.         frees = gen.scope.get_free_vars()
  693.         if frees:
  694.             for name in frees:
  695.                 self.emit('LOAD_CLOSURE', name)
  696.             
  697.             self.emit('LOAD_CONST', gen)
  698.             self.emit('MAKE_CLOSURE', 0)
  699.         else:
  700.             self.emit('LOAD_CONST', gen)
  701.             self.emit('MAKE_FUNCTION', 0)
  702.         self.visit(node.code.quals[0].iter)
  703.         self.emit('GET_ITER')
  704.         self.emit('CALL_FUNCTION', 1)
  705.  
  706.     
  707.     def visitGenExprInner(self, node):
  708.         self.set_lineno(node)
  709.         stack = []
  710.         for i, for_ in zip(range(len(node.quals)), node.quals):
  711.             (start, anchor) = self.visit(for_)
  712.             cont = None
  713.             for if_ in for_.ifs:
  714.                 if cont is None:
  715.                     cont = self.newBlock()
  716.                 
  717.                 self.visit(if_, cont)
  718.             
  719.             stack.insert(0, (start, cont, anchor))
  720.         
  721.         self.visit(node.expr)
  722.         self.emit('YIELD_VALUE')
  723.         for start, cont, anchor in stack:
  724.             if cont:
  725.                 skip_one = self.newBlock()
  726.                 self.emit('JUMP_FORWARD', skip_one)
  727.                 self.startBlock(cont)
  728.                 self.emit('POP_TOP')
  729.                 self.nextBlock(skip_one)
  730.             
  731.             self.emit('JUMP_ABSOLUTE', start)
  732.             self.startBlock(anchor)
  733.         
  734.         self.emit('LOAD_CONST', None)
  735.  
  736.     
  737.     def visitGenExprFor(self, node):
  738.         start = self.newBlock()
  739.         anchor = self.newBlock()
  740.         if node.is_outmost:
  741.             self.loadName('[outmost-iterable]')
  742.         else:
  743.             self.visit(node.iter)
  744.             self.emit('GET_ITER')
  745.         self.nextBlock(start)
  746.         self.set_lineno(node, force = True)
  747.         self.emit('FOR_ITER', anchor)
  748.         self.nextBlock()
  749.         self.visit(node.assign)
  750.         return (start, anchor)
  751.  
  752.     
  753.     def visitGenExprIf(self, node, branch):
  754.         self.set_lineno(node, force = True)
  755.         self.visit(node.test)
  756.         self.emit('JUMP_IF_FALSE', branch)
  757.         self.newBlock()
  758.         self.emit('POP_TOP')
  759.  
  760.     
  761.     def visitAssert(self, node):
  762.         if __debug__:
  763.             end = self.newBlock()
  764.             self.set_lineno(node)
  765.             self.nextBlock()
  766.             self.visit(node.test)
  767.             self.emit('JUMP_IF_TRUE', end)
  768.             self.nextBlock()
  769.             self.emit('POP_TOP')
  770.             self.emit('LOAD_GLOBAL', 'AssertionError')
  771.             if node.fail:
  772.                 self.visit(node.fail)
  773.                 self.emit('RAISE_VARARGS', 2)
  774.             else:
  775.                 self.emit('RAISE_VARARGS', 1)
  776.             self.nextBlock(end)
  777.             self.emit('POP_TOP')
  778.         
  779.  
  780.     
  781.     def visitRaise(self, node):
  782.         self.set_lineno(node)
  783.         n = 0
  784.         if node.expr1:
  785.             self.visit(node.expr1)
  786.             n = n + 1
  787.         
  788.         if node.expr2:
  789.             self.visit(node.expr2)
  790.             n = n + 1
  791.         
  792.         if node.expr3:
  793.             self.visit(node.expr3)
  794.             n = n + 1
  795.         
  796.         self.emit('RAISE_VARARGS', n)
  797.  
  798.     
  799.     def visitTryExcept(self, node):
  800.         body = self.newBlock()
  801.         handlers = self.newBlock()
  802.         end = self.newBlock()
  803.         if node.else_:
  804.             lElse = self.newBlock()
  805.         else:
  806.             lElse = end
  807.         self.set_lineno(node)
  808.         self.emit('SETUP_EXCEPT', handlers)
  809.         self.nextBlock(body)
  810.         self.setups.push((EXCEPT, body))
  811.         self.visit(node.body)
  812.         self.emit('POP_BLOCK')
  813.         self.setups.pop()
  814.         self.emit('JUMP_FORWARD', lElse)
  815.         self.startBlock(handlers)
  816.         last = len(node.handlers) - 1
  817.         for i in range(len(node.handlers)):
  818.             (expr, target, body) = node.handlers[i]
  819.             self.set_lineno(expr)
  820.             if expr:
  821.                 self.emit('DUP_TOP')
  822.                 self.visit(expr)
  823.                 self.emit('COMPARE_OP', 'exception match')
  824.                 next = self.newBlock()
  825.                 self.emit('JUMP_IF_FALSE', next)
  826.                 self.nextBlock()
  827.                 self.emit('POP_TOP')
  828.             
  829.             self.emit('POP_TOP')
  830.             if target:
  831.                 self.visit(target)
  832.             else:
  833.                 self.emit('POP_TOP')
  834.             self.emit('POP_TOP')
  835.             self.visit(body)
  836.             self.emit('JUMP_FORWARD', end)
  837.             if expr:
  838.                 self.nextBlock(next)
  839.             else:
  840.                 self.nextBlock()
  841.             if expr:
  842.                 self.emit('POP_TOP')
  843.                 continue
  844.         
  845.         self.emit('END_FINALLY')
  846.         if node.else_:
  847.             self.nextBlock(lElse)
  848.             self.visit(node.else_)
  849.         
  850.         self.nextBlock(end)
  851.  
  852.     
  853.     def visitTryFinally(self, node):
  854.         body = self.newBlock()
  855.         final = self.newBlock()
  856.         self.set_lineno(node)
  857.         self.emit('SETUP_FINALLY', final)
  858.         self.nextBlock(body)
  859.         self.setups.push((TRY_FINALLY, body))
  860.         self.visit(node.body)
  861.         self.emit('POP_BLOCK')
  862.         self.setups.pop()
  863.         self.emit('LOAD_CONST', None)
  864.         self.nextBlock(final)
  865.         self.setups.push((END_FINALLY, final))
  866.         self.visit(node.final)
  867.         self.emit('END_FINALLY')
  868.         self.setups.pop()
  869.  
  870.     
  871.     def visitDiscard(self, node):
  872.         self.set_lineno(node)
  873.         self.visit(node.expr)
  874.         self.emit('POP_TOP')
  875.  
  876.     
  877.     def visitConst(self, node):
  878.         self.emit('LOAD_CONST', node.value)
  879.  
  880.     
  881.     def visitKeyword(self, node):
  882.         self.emit('LOAD_CONST', node.name)
  883.         self.visit(node.expr)
  884.  
  885.     
  886.     def visitGlobal(self, node):
  887.         pass
  888.  
  889.     
  890.     def visitName(self, node):
  891.         self.set_lineno(node)
  892.         self.loadName(node.name)
  893.  
  894.     
  895.     def visitPass(self, node):
  896.         self.set_lineno(node)
  897.  
  898.     
  899.     def visitImport(self, node):
  900.         self.set_lineno(node)
  901.         for name, alias in node.names:
  902.             if VERSION > 1:
  903.                 self.emit('LOAD_CONST', None)
  904.             
  905.             self.emit('IMPORT_NAME', name)
  906.             mod = name.split('.')[0]
  907.             if alias:
  908.                 self._resolveDots(name)
  909.                 self.storeName(alias)
  910.                 continue
  911.             self.storeName(mod)
  912.         
  913.  
  914.     
  915.     def visitFrom(self, node):
  916.         self.set_lineno(node)
  917.         fromlist = map((lambda .0: (name, alias) = .0name), node.names)
  918.         if VERSION > 1:
  919.             self.emit('LOAD_CONST', tuple(fromlist))
  920.         
  921.         self.emit('IMPORT_NAME', node.modname)
  922.         for name, alias in node.names:
  923.             if VERSION > 1:
  924.                 if name == '*':
  925.                     self.namespace = 0
  926.                     self.emit('IMPORT_STAR')
  927.                     if not len(node.names) == 1:
  928.                         raise AssertionError
  929.                     return None
  930.                 else:
  931.                     self.emit('IMPORT_FROM', name)
  932.                     self._resolveDots(name)
  933.                     if not alias:
  934.                         pass
  935.                     self.storeName(name)
  936.             name == '*'
  937.             self.emit('IMPORT_FROM', name)
  938.         
  939.         self.emit('POP_TOP')
  940.  
  941.     
  942.     def _resolveDots(self, name):
  943.         elts = name.split('.')
  944.         if len(elts) == 1:
  945.             return None
  946.         
  947.         for elt in elts[1:]:
  948.             self.emit('LOAD_ATTR', elt)
  949.         
  950.  
  951.     
  952.     def visitGetattr(self, node):
  953.         self.visit(node.expr)
  954.         self.emit('LOAD_ATTR', self.mangle(node.attrname))
  955.  
  956.     
  957.     def visitAssign(self, node):
  958.         self.set_lineno(node)
  959.         self.visit(node.expr)
  960.         dups = len(node.nodes) - 1
  961.         for i in range(len(node.nodes)):
  962.             elt = node.nodes[i]
  963.             if i < dups:
  964.                 self.emit('DUP_TOP')
  965.             
  966.             if isinstance(elt, ast.Node):
  967.                 self.visit(elt)
  968.                 continue
  969.         
  970.  
  971.     
  972.     def visitAssName(self, node):
  973.         if node.flags == 'OP_ASSIGN':
  974.             self.storeName(node.name)
  975.         elif node.flags == 'OP_DELETE':
  976.             self.set_lineno(node)
  977.             self.delName(node.name)
  978.         else:
  979.             print 'oops', node.flags
  980.  
  981.     
  982.     def visitAssAttr(self, node):
  983.         self.visit(node.expr)
  984.         if node.flags == 'OP_ASSIGN':
  985.             self.emit('STORE_ATTR', self.mangle(node.attrname))
  986.         elif node.flags == 'OP_DELETE':
  987.             self.emit('DELETE_ATTR', self.mangle(node.attrname))
  988.         else:
  989.             print 'warning: unexpected flags:', node.flags
  990.             print node
  991.  
  992.     
  993.     def _visitAssSequence(self, node, op = 'UNPACK_SEQUENCE'):
  994.         if findOp(node) != 'OP_DELETE':
  995.             self.emit(op, len(node.nodes))
  996.         
  997.         for child in node.nodes:
  998.             self.visit(child)
  999.         
  1000.  
  1001.     if VERSION > 1:
  1002.         visitAssTuple = _visitAssSequence
  1003.         visitAssList = _visitAssSequence
  1004.     else:
  1005.         
  1006.         def visitAssTuple(self, node):
  1007.             self._visitAssSequence(node, 'UNPACK_TUPLE')
  1008.  
  1009.         
  1010.         def visitAssList(self, node):
  1011.             self._visitAssSequence(node, 'UNPACK_LIST')
  1012.  
  1013.     
  1014.     def visitAugAssign(self, node):
  1015.         self.set_lineno(node)
  1016.         aug_node = wrap_aug(node.node)
  1017.         self.visit(aug_node, 'load')
  1018.         self.visit(node.expr)
  1019.         self.emit(self._augmented_opcode[node.op])
  1020.         self.visit(aug_node, 'store')
  1021.  
  1022.     _augmented_opcode = {
  1023.         '+=': 'INPLACE_ADD',
  1024.         '-=': 'INPLACE_SUBTRACT',
  1025.         '*=': 'INPLACE_MULTIPLY',
  1026.         '/=': 'INPLACE_DIVIDE',
  1027.         '//=': 'INPLACE_FLOOR_DIVIDE',
  1028.         '%=': 'INPLACE_MODULO',
  1029.         '**=': 'INPLACE_POWER',
  1030.         '>>=': 'INPLACE_RSHIFT',
  1031.         '<<=': 'INPLACE_LSHIFT',
  1032.         '&=': 'INPLACE_AND',
  1033.         '^=': 'INPLACE_XOR',
  1034.         '|=': 'INPLACE_OR' }
  1035.     
  1036.     def visitAugName(self, node, mode):
  1037.         if mode == 'load':
  1038.             self.loadName(node.name)
  1039.         elif mode == 'store':
  1040.             self.storeName(node.name)
  1041.         
  1042.  
  1043.     
  1044.     def visitAugGetattr(self, node, mode):
  1045.         if mode == 'load':
  1046.             self.visit(node.expr)
  1047.             self.emit('DUP_TOP')
  1048.             self.emit('LOAD_ATTR', self.mangle(node.attrname))
  1049.         elif mode == 'store':
  1050.             self.emit('ROT_TWO')
  1051.             self.emit('STORE_ATTR', self.mangle(node.attrname))
  1052.         
  1053.  
  1054.     
  1055.     def visitAugSlice(self, node, mode):
  1056.         if mode == 'load':
  1057.             self.visitSlice(node, 1)
  1058.         elif mode == 'store':
  1059.             slice = 0
  1060.             if node.lower:
  1061.                 slice = slice | 1
  1062.             
  1063.             if node.upper:
  1064.                 slice = slice | 2
  1065.             
  1066.             if slice == 0:
  1067.                 self.emit('ROT_TWO')
  1068.             elif slice == 3:
  1069.                 self.emit('ROT_FOUR')
  1070.             else:
  1071.                 self.emit('ROT_THREE')
  1072.             self.emit('STORE_SLICE+%d' % slice)
  1073.         
  1074.  
  1075.     
  1076.     def visitAugSubscript(self, node, mode):
  1077.         if len(node.subs) > 1:
  1078.             raise SyntaxError, 'augmented assignment to tuple is not possible'
  1079.         
  1080.         if mode == 'load':
  1081.             self.visitSubscript(node, 1)
  1082.         elif mode == 'store':
  1083.             self.emit('ROT_THREE')
  1084.             self.emit('STORE_SUBSCR')
  1085.         
  1086.  
  1087.     
  1088.     def visitExec(self, node):
  1089.         self.visit(node.expr)
  1090.         if node.locals is None:
  1091.             self.emit('LOAD_CONST', None)
  1092.         else:
  1093.             self.visit(node.locals)
  1094.         if node.globals is None:
  1095.             self.emit('DUP_TOP')
  1096.         else:
  1097.             self.visit(node.globals)
  1098.         self.emit('EXEC_STMT')
  1099.  
  1100.     
  1101.     def visitCallFunc(self, node):
  1102.         pos = 0
  1103.         kw = 0
  1104.         self.set_lineno(node)
  1105.         self.visit(node.node)
  1106.         for arg in node.args:
  1107.             self.visit(arg)
  1108.             if isinstance(arg, ast.Keyword):
  1109.                 kw = kw + 1
  1110.                 continue
  1111.             pos = pos + 1
  1112.         
  1113.         if node.star_args is not None:
  1114.             self.visit(node.star_args)
  1115.         
  1116.         if node.dstar_args is not None:
  1117.             self.visit(node.dstar_args)
  1118.         
  1119.         have_star = node.star_args is not None
  1120.         have_dstar = node.dstar_args is not None
  1121.         opcode = callfunc_opcode_info[(have_star, have_dstar)]
  1122.         self.emit(opcode, kw << 8 | pos)
  1123.  
  1124.     
  1125.     def visitPrint(self, node, newline = 0):
  1126.         self.set_lineno(node)
  1127.         if node.dest:
  1128.             self.visit(node.dest)
  1129.         
  1130.         for child in node.nodes:
  1131.             if node.dest:
  1132.                 self.emit('DUP_TOP')
  1133.             
  1134.             self.visit(child)
  1135.             if node.dest:
  1136.                 self.emit('ROT_TWO')
  1137.                 self.emit('PRINT_ITEM_TO')
  1138.                 continue
  1139.             self.emit('PRINT_ITEM')
  1140.         
  1141.         if node.dest and not newline:
  1142.             self.emit('POP_TOP')
  1143.         
  1144.  
  1145.     
  1146.     def visitPrintnl(self, node):
  1147.         self.visitPrint(node, newline = 1)
  1148.         if node.dest:
  1149.             self.emit('PRINT_NEWLINE_TO')
  1150.         else:
  1151.             self.emit('PRINT_NEWLINE')
  1152.  
  1153.     
  1154.     def visitReturn(self, node):
  1155.         self.set_lineno(node)
  1156.         self.visit(node.value)
  1157.         self.emit('RETURN_VALUE')
  1158.  
  1159.     
  1160.     def visitYield(self, node):
  1161.         self.set_lineno(node)
  1162.         self.visit(node.value)
  1163.         self.emit('YIELD_VALUE')
  1164.  
  1165.     
  1166.     def visitSlice(self, node, aug_flag = None):
  1167.         self.visit(node.expr)
  1168.         slice = 0
  1169.         if node.lower:
  1170.             self.visit(node.lower)
  1171.             slice = slice | 1
  1172.         
  1173.         if node.upper:
  1174.             self.visit(node.upper)
  1175.             slice = slice | 2
  1176.         
  1177.         if aug_flag:
  1178.             if slice == 0:
  1179.                 self.emit('DUP_TOP')
  1180.             elif slice == 3:
  1181.                 self.emit('DUP_TOPX', 3)
  1182.             else:
  1183.                 self.emit('DUP_TOPX', 2)
  1184.         
  1185.         if node.flags == 'OP_APPLY':
  1186.             self.emit('SLICE+%d' % slice)
  1187.         elif node.flags == 'OP_ASSIGN':
  1188.             self.emit('STORE_SLICE+%d' % slice)
  1189.         elif node.flags == 'OP_DELETE':
  1190.             self.emit('DELETE_SLICE+%d' % slice)
  1191.         else:
  1192.             print 'weird slice', node.flags
  1193.             raise 
  1194.  
  1195.     
  1196.     def visitSubscript(self, node, aug_flag = None):
  1197.         self.visit(node.expr)
  1198.         for sub in node.subs:
  1199.             self.visit(sub)
  1200.         
  1201.         if aug_flag:
  1202.             self.emit('DUP_TOPX', 2)
  1203.         
  1204.         if len(node.subs) > 1:
  1205.             self.emit('BUILD_TUPLE', len(node.subs))
  1206.         
  1207.         if node.flags == 'OP_APPLY':
  1208.             self.emit('BINARY_SUBSCR')
  1209.         elif node.flags == 'OP_ASSIGN':
  1210.             self.emit('STORE_SUBSCR')
  1211.         elif node.flags == 'OP_DELETE':
  1212.             self.emit('DELETE_SUBSCR')
  1213.         
  1214.  
  1215.     
  1216.     def binaryOp(self, node, op):
  1217.         self.visit(node.left)
  1218.         self.visit(node.right)
  1219.         self.emit(op)
  1220.  
  1221.     
  1222.     def visitAdd(self, node):
  1223.         return self.binaryOp(node, 'BINARY_ADD')
  1224.  
  1225.     
  1226.     def visitSub(self, node):
  1227.         return self.binaryOp(node, 'BINARY_SUBTRACT')
  1228.  
  1229.     
  1230.     def visitMul(self, node):
  1231.         return self.binaryOp(node, 'BINARY_MULTIPLY')
  1232.  
  1233.     
  1234.     def visitDiv(self, node):
  1235.         return self.binaryOp(node, self._div_op)
  1236.  
  1237.     
  1238.     def visitFloorDiv(self, node):
  1239.         return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
  1240.  
  1241.     
  1242.     def visitMod(self, node):
  1243.         return self.binaryOp(node, 'BINARY_MODULO')
  1244.  
  1245.     
  1246.     def visitPower(self, node):
  1247.         return self.binaryOp(node, 'BINARY_POWER')
  1248.  
  1249.     
  1250.     def visitLeftShift(self, node):
  1251.         return self.binaryOp(node, 'BINARY_LSHIFT')
  1252.  
  1253.     
  1254.     def visitRightShift(self, node):
  1255.         return self.binaryOp(node, 'BINARY_RSHIFT')
  1256.  
  1257.     
  1258.     def unaryOp(self, node, op):
  1259.         self.visit(node.expr)
  1260.         self.emit(op)
  1261.  
  1262.     
  1263.     def visitInvert(self, node):
  1264.         return self.unaryOp(node, 'UNARY_INVERT')
  1265.  
  1266.     
  1267.     def visitUnarySub(self, node):
  1268.         return self.unaryOp(node, 'UNARY_NEGATIVE')
  1269.  
  1270.     
  1271.     def visitUnaryAdd(self, node):
  1272.         return self.unaryOp(node, 'UNARY_POSITIVE')
  1273.  
  1274.     
  1275.     def visitUnaryInvert(self, node):
  1276.         return self.unaryOp(node, 'UNARY_INVERT')
  1277.  
  1278.     
  1279.     def visitNot(self, node):
  1280.         return self.unaryOp(node, 'UNARY_NOT')
  1281.  
  1282.     
  1283.     def visitBackquote(self, node):
  1284.         return self.unaryOp(node, 'UNARY_CONVERT')
  1285.  
  1286.     
  1287.     def bitOp(self, nodes, op):
  1288.         self.visit(nodes[0])
  1289.         for node in nodes[1:]:
  1290.             self.visit(node)
  1291.             self.emit(op)
  1292.         
  1293.  
  1294.     
  1295.     def visitBitand(self, node):
  1296.         return self.bitOp(node.nodes, 'BINARY_AND')
  1297.  
  1298.     
  1299.     def visitBitor(self, node):
  1300.         return self.bitOp(node.nodes, 'BINARY_OR')
  1301.  
  1302.     
  1303.     def visitBitxor(self, node):
  1304.         return self.bitOp(node.nodes, 'BINARY_XOR')
  1305.  
  1306.     
  1307.     def visitEllipsis(self, node):
  1308.         self.emit('LOAD_CONST', Ellipsis)
  1309.  
  1310.     
  1311.     def visitTuple(self, node):
  1312.         self.set_lineno(node)
  1313.         for elt in node.nodes:
  1314.             self.visit(elt)
  1315.         
  1316.         self.emit('BUILD_TUPLE', len(node.nodes))
  1317.  
  1318.     
  1319.     def visitList(self, node):
  1320.         self.set_lineno(node)
  1321.         for elt in node.nodes:
  1322.             self.visit(elt)
  1323.         
  1324.         self.emit('BUILD_LIST', len(node.nodes))
  1325.  
  1326.     
  1327.     def visitSliceobj(self, node):
  1328.         for child in node.nodes:
  1329.             self.visit(child)
  1330.         
  1331.         self.emit('BUILD_SLICE', len(node.nodes))
  1332.  
  1333.     
  1334.     def visitDict(self, node):
  1335.         self.set_lineno(node)
  1336.         self.emit('BUILD_MAP', 0)
  1337.         for k, v in node.items:
  1338.             self.emit('DUP_TOP')
  1339.             self.visit(k)
  1340.             self.visit(v)
  1341.             self.emit('ROT_THREE')
  1342.             self.emit('STORE_SUBSCR')
  1343.         
  1344.  
  1345.  
  1346.  
  1347. class NestedScopeMixin:
  1348.     '''Defines initClass() for nested scoping (Python 2.2-compatible)'''
  1349.     
  1350.     def initClass(self):
  1351.         self.__class__.NameFinder = LocalNameFinder
  1352.         self.__class__.FunctionGen = FunctionCodeGenerator
  1353.         self.__class__.ClassGen = ClassCodeGenerator
  1354.  
  1355.  
  1356.  
  1357. class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
  1358.     __super_init = CodeGenerator.__init__
  1359.     scopes = None
  1360.     
  1361.     def __init__(self, tree):
  1362.         self.graph = pyassem.PyFlowGraph('<module>', tree.filename)
  1363.         self.futures = future.find_futures(tree)
  1364.         self._ModuleCodeGenerator__super_init()
  1365.         walk(tree, self)
  1366.  
  1367.     
  1368.     def get_module(self):
  1369.         return self
  1370.  
  1371.  
  1372.  
  1373. class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
  1374.     __super_init = CodeGenerator.__init__
  1375.     scopes = None
  1376.     futures = ()
  1377.     
  1378.     def __init__(self, tree):
  1379.         self.graph = pyassem.PyFlowGraph('<expression>', tree.filename)
  1380.         self._ExpressionCodeGenerator__super_init()
  1381.         walk(tree, self)
  1382.  
  1383.     
  1384.     def get_module(self):
  1385.         return self
  1386.  
  1387.  
  1388.  
  1389. class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
  1390.     __super_init = CodeGenerator.__init__
  1391.     scopes = None
  1392.     futures = ()
  1393.     
  1394.     def __init__(self, tree):
  1395.         self.graph = pyassem.PyFlowGraph('<interactive>', tree.filename)
  1396.         self._InteractiveCodeGenerator__super_init()
  1397.         self.set_lineno(tree)
  1398.         walk(tree, self)
  1399.         self.emit('RETURN_VALUE')
  1400.  
  1401.     
  1402.     def get_module(self):
  1403.         return self
  1404.  
  1405.     
  1406.     def visitDiscard(self, node):
  1407.         self.visit(node.expr)
  1408.         self.emit('PRINT_EXPR')
  1409.  
  1410.  
  1411.  
  1412. class AbstractFunctionCode:
  1413.     optimized = 1
  1414.     lambdaCount = 0
  1415.     
  1416.     def __init__(self, func, scopes, isLambda, class_name, mod):
  1417.         self.class_name = class_name
  1418.         self.module = mod
  1419.         if isLambda:
  1420.             klass = FunctionCodeGenerator
  1421.             name = '<lambda.%d>' % klass.lambdaCount
  1422.             klass.lambdaCount = klass.lambdaCount + 1
  1423.         else:
  1424.             name = func.name
  1425.         (args, hasTupleArg) = generateArgList(func.argnames)
  1426.         self.graph = pyassem.PyFlowGraph(name, func.filename, args, optimized = 1)
  1427.         self.isLambda = isLambda
  1428.         self.super_init()
  1429.         if not isLambda and func.doc:
  1430.             self.setDocstring(func.doc)
  1431.         
  1432.         lnf = walk(func.code, self.NameFinder(args), verbose = 0)
  1433.         self.locals.push(lnf.getLocals())
  1434.         if func.varargs:
  1435.             self.graph.setFlag(CO_VARARGS)
  1436.         
  1437.         if func.kwargs:
  1438.             self.graph.setFlag(CO_VARKEYWORDS)
  1439.         
  1440.         self.set_lineno(func)
  1441.         if hasTupleArg:
  1442.             self.generateArgUnpack(func.argnames)
  1443.         
  1444.  
  1445.     
  1446.     def get_module(self):
  1447.         return self.module
  1448.  
  1449.     
  1450.     def finish(self):
  1451.         self.graph.startExitBlock()
  1452.         if not self.isLambda:
  1453.             self.emit('LOAD_CONST', None)
  1454.         
  1455.         self.emit('RETURN_VALUE')
  1456.  
  1457.     
  1458.     def generateArgUnpack(self, args):
  1459.         for i in range(len(args)):
  1460.             arg = args[i]
  1461.             if type(arg) == types.TupleType:
  1462.                 self.emit('LOAD_FAST', '.%d' % i * 2)
  1463.                 self.unpackSequence(arg)
  1464.                 continue
  1465.         
  1466.  
  1467.     
  1468.     def unpackSequence(self, tup):
  1469.         if VERSION > 1:
  1470.             self.emit('UNPACK_SEQUENCE', len(tup))
  1471.         else:
  1472.             self.emit('UNPACK_TUPLE', len(tup))
  1473.         for elt in tup:
  1474.             if type(elt) == types.TupleType:
  1475.                 self.unpackSequence(elt)
  1476.                 continue
  1477.             self._nameOp('STORE', elt)
  1478.         
  1479.  
  1480.     unpackTuple = unpackSequence
  1481.  
  1482.  
  1483. class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode, CodeGenerator):
  1484.     super_init = CodeGenerator.__init__
  1485.     scopes = None
  1486.     __super_init = AbstractFunctionCode.__init__
  1487.     
  1488.     def __init__(self, func, scopes, isLambda, class_name, mod):
  1489.         self.scopes = scopes
  1490.         self.scope = scopes[func]
  1491.         self._FunctionCodeGenerator__super_init(func, scopes, isLambda, class_name, mod)
  1492.         self.graph.setFreeVars(self.scope.get_free_vars())
  1493.         self.graph.setCellVars(self.scope.get_cell_vars())
  1494.         if self.scope.generator is not None:
  1495.             self.graph.setFlag(CO_GENERATOR)
  1496.         
  1497.  
  1498.  
  1499.  
  1500. class GenExprCodeGenerator(NestedScopeMixin, AbstractFunctionCode, CodeGenerator):
  1501.     super_init = CodeGenerator.__init__
  1502.     scopes = None
  1503.     __super_init = AbstractFunctionCode.__init__
  1504.     
  1505.     def __init__(self, gexp, scopes, class_name, mod):
  1506.         self.scopes = scopes
  1507.         self.scope = scopes[gexp]
  1508.         self._GenExprCodeGenerator__super_init(gexp, scopes, 1, class_name, mod)
  1509.         self.graph.setFreeVars(self.scope.get_free_vars())
  1510.         self.graph.setCellVars(self.scope.get_cell_vars())
  1511.         self.graph.setFlag(CO_GENERATOR)
  1512.  
  1513.  
  1514.  
  1515. class AbstractClassCode:
  1516.     
  1517.     def __init__(self, klass, scopes, module):
  1518.         self.class_name = klass.name
  1519.         self.module = module
  1520.         self.graph = pyassem.PyFlowGraph(klass.name, klass.filename, optimized = 0, klass = 1)
  1521.         self.super_init()
  1522.         lnf = walk(klass.code, self.NameFinder(), verbose = 0)
  1523.         self.locals.push(lnf.getLocals())
  1524.         self.graph.setFlag(CO_NEWLOCALS)
  1525.         if klass.doc:
  1526.             self.setDocstring(klass.doc)
  1527.         
  1528.  
  1529.     
  1530.     def get_module(self):
  1531.         return self.module
  1532.  
  1533.     
  1534.     def finish(self):
  1535.         self.graph.startExitBlock()
  1536.         self.emit('LOAD_LOCALS')
  1537.         self.emit('RETURN_VALUE')
  1538.  
  1539.  
  1540.  
  1541. class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
  1542.     super_init = CodeGenerator.__init__
  1543.     scopes = None
  1544.     __super_init = AbstractClassCode.__init__
  1545.     
  1546.     def __init__(self, klass, scopes, module):
  1547.         self.scopes = scopes
  1548.         self.scope = scopes[klass]
  1549.         self._ClassCodeGenerator__super_init(klass, scopes, module)
  1550.         self.graph.setFreeVars(self.scope.get_free_vars())
  1551.         self.graph.setCellVars(self.scope.get_cell_vars())
  1552.         self.set_lineno(klass)
  1553.         self.emit('LOAD_GLOBAL', '__name__')
  1554.         self.storeName('__module__')
  1555.         if klass.doc:
  1556.             self.emit('LOAD_CONST', klass.doc)
  1557.             self.storeName('__doc__')
  1558.         
  1559.  
  1560.  
  1561.  
  1562. def generateArgList(arglist):
  1563.     '''Generate an arg list marking TupleArgs'''
  1564.     args = []
  1565.     extra = []
  1566.     count = 0
  1567.     for i in range(len(arglist)):
  1568.         elt = arglist[i]
  1569.         if type(elt) == types.StringType:
  1570.             args.append(elt)
  1571.             continue
  1572.         if type(elt) == types.TupleType:
  1573.             args.append(TupleArg(i * 2, elt))
  1574.             extra.extend(misc.flatten(elt))
  1575.             count = count + 1
  1576.             continue
  1577.         raise ValueError, 'unexpect argument type:', elt
  1578.     
  1579.     return (args + extra, count)
  1580.  
  1581.  
  1582. def findOp(node):
  1583.     '''Find the op (DELETE, LOAD, STORE) in an AssTuple tree'''
  1584.     v = OpFinder()
  1585.     walk(node, v, verbose = 0)
  1586.     return v.op
  1587.  
  1588.  
  1589. class OpFinder:
  1590.     
  1591.     def __init__(self):
  1592.         self.op = None
  1593.  
  1594.     
  1595.     def visitAssName(self, node):
  1596.         if self.op is None:
  1597.             self.op = node.flags
  1598.         elif self.op != node.flags:
  1599.             raise ValueError, 'mixed ops in stmt'
  1600.         
  1601.  
  1602.     visitAssAttr = visitAssName
  1603.     visitSubscript = visitAssName
  1604.  
  1605.  
  1606. class Delegator:
  1607.     '''Base class to support delegation for augmented assignment nodes
  1608.  
  1609.     To generator code for augmented assignments, we use the following
  1610.     wrapper classes.  In visitAugAssign, the left-hand expression node
  1611.     is visited twice.  The first time the visit uses the normal method
  1612.     for that node .  The second time the visit uses a different method
  1613.     that generates the appropriate code to perform the assignment.
  1614.     These delegator classes wrap the original AST nodes in order to
  1615.     support the variant visit methods.
  1616.     '''
  1617.     
  1618.     def __init__(self, obj):
  1619.         self.obj = obj
  1620.  
  1621.     
  1622.     def __getattr__(self, attr):
  1623.         return getattr(self.obj, attr)
  1624.  
  1625.  
  1626.  
  1627. class AugGetattr(Delegator):
  1628.     pass
  1629.  
  1630.  
  1631. class AugName(Delegator):
  1632.     pass
  1633.  
  1634.  
  1635. class AugSlice(Delegator):
  1636.     pass
  1637.  
  1638.  
  1639. class AugSubscript(Delegator):
  1640.     pass
  1641.  
  1642. wrapper = {
  1643.     ast.Getattr: AugGetattr,
  1644.     ast.Name: AugName,
  1645.     ast.Slice: AugSlice,
  1646.     ast.Subscript: AugSubscript }
  1647.  
  1648. def wrap_aug(node):
  1649.     return wrapper[node.__class__](node)
  1650.  
  1651. if __name__ == '__main__':
  1652.     for file in sys.argv[1:]:
  1653.         compileFile(file)
  1654.     
  1655.  
  1656.